home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / RegionToRectangles Folder / EachRegionRect.c next >
Text File  |  1993-11-13  |  2KB  |  100 lines

  1.  
  2.  
  3. /*    I was going to put "copyright (c)..." but that seemed
  4.     a bit presumptuous given that regions were designed by
  5.     Bill Atkinson. So,
  6.     
  7.     Written by Hugh Fisher, March 1993.
  8.     
  9.     This code is standard commercial quality: I think it
  10.     works, and I'll fix any bugs you find, but it's not
  11.     MY responsibility even if your computer melts.
  12.                                                     */
  13.  
  14. void EachRegionRect (RgnHandle r, void (* proc)(Rect *));
  15.  
  16. void EachRegionRect (RgnHandle r, void (* proc)(Rect *))
  17. {
  18. #define EndMark     32767
  19. #define MaxY        32767
  20. #define StackMax    1024
  21.  
  22.     typedef struct {
  23.         short    size;
  24.         Rect    bbox;
  25.         short    data[];
  26.         } ** Internal;
  27.     
  28.     Internal region;
  29.     short     width, xAdjust, y, index, x1, x2, x;
  30.     Rect     box;
  31.     short     stackStorage[1024];
  32.     short *     buffer;
  33.     
  34.     region = (Internal)r;
  35.     
  36.     /* Check for plain rectangle */
  37.     if ((**region).size == 10) {
  38.         proc(&(**region).bbox);
  39.         return;
  40.     }
  41.     /* Got to scale x coordinates into range 0..something */
  42.     xAdjust = (**region).bbox.left;
  43.     width = (**region).bbox.right - xAdjust;
  44.     /* Most regions will be less than 1024 pixels wide */
  45.     if (width < StackMax)
  46.         buffer = stackStorage;
  47.     else {
  48.         buffer = (short *)NewPtr(width * 2);
  49.         if (buffer == NULL)
  50.             /* Truly humungous region or very low on memory.
  51.                Quietly doing nothing seems to be the
  52.                traditional Quickdraw response. */
  53.             return;
  54.     }
  55.     /* Initialise scan line list to bottom edges */
  56.     for (x = (**region).bbox.left; x < (**region).bbox.right; x++)
  57.         buffer[x - xAdjust] = MaxY;
  58.     index = 0;
  59.     /* Loop until we hit an empty scan line */
  60.     while ((**region).data[index] != EndMark) {
  61.         y = (**region).data[index];
  62.         index ++;
  63.         /* Loop through horizontal runs on this line */
  64.         while ((**region).data[index] != EndMark) {
  65.             x1 = (**region).data[index];
  66.             index ++;
  67.             x2 = (**region).data[index];
  68.             index ++;
  69.             x = x1;
  70.             while (x < x2) {
  71.                 if (buffer[x - xAdjust] < y) {
  72.                     /* We have a bottom edge - how long for? */
  73.                     box.left = x;
  74.                     box.top  = buffer[x - xAdjust];
  75.                     while (x < x2 && buffer[x - xAdjust] == box.top) {
  76.                         buffer[x - xAdjust] = MaxY;
  77.                         x ++;
  78.                     }
  79.                     /* Pass to client proc */
  80.                     box.right  = x;
  81.                     box.bottom = y;
  82.                     proc(&box);
  83.                 } else {
  84.                     /* This becomes a top edge */
  85.                     buffer[x - xAdjust] = y;
  86.                     x ++;
  87.                 }
  88.             }
  89.         }
  90.         index ++;
  91.     }
  92.     /* Clean up after ourselves */
  93.     if (width >= StackMax)
  94.         DisposPtr((Ptr)buffer);
  95. #undef EndMark
  96. #undef MaxY
  97. #undef StackMax
  98. }
  99.  
  100.